package me.test;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.Principal;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.security.cas.authentication.CasAuthenticationToken;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
@Controller
public class MyController {
private Logger logger = LoggerFactory.getLogger(MyController.class);
@Value("#{appCfg['testProxy.url.appointment']}")
private String appointmentUrl;
@Value("#{appCfg['testProxy.url.staff']}")
private String staffUrl;
@RequestMapping("/testProxy")
// 这些权限控制的注解也可以应用到接口上
public String testProxy(Map<String, Object> modelMap, Principal principal) throws UnsupportedEncodingException {
RestTemplate rest = new RestTemplate();
rest.setErrorHandler(new ResponseErrorHandler() {
public boolean hasError(ClientHttpResponse response) throws IOException {
return false;
}
public void handleError(ClientHttpResponse response) throws IOException {
}
});
CasAuthenticationToken token = null;
if (principal instanceof CasAuthenticationToken) {
token = (CasAuthenticationToken) principal;
}
// FIXME : Why SecurityContextHolder.getContext().getPrincipal() != httpServletRequest.getUserPrincipal();
// Actually is User != CasAuthenticationToken
// 调用 appointment 服务
String appointmentServiceUrl = appointmentUrl;
if (token != null) {
String proxyTicket = token.getAssertion().getPrincipal().getProxyTicketFor(appointmentUrl);
appointmentServiceUrl = appointmentUrl + "?ticket=" + URLEncoder.encode(proxyTicket, "UTF-8");
}
ResponseEntity<String> respEntity = rest.getForEntity(appointmentServiceUrl, String.class);
modelMap.put("appointmentServiceUrl", appointmentServiceUrl);
modelMap.put("appointmentServiceRespCode", respEntity.getStatusCode().value());
modelMap.put("appointmentServiceResp", respEntity.getBody());
// 使用同一个 ProxyToken 应当会失败
if (token != null) {
respEntity = rest.getForEntity(appointmentServiceUrl, String.class);
HttpStatus status = respEntity.getStatusCode();
if (HttpStatus.OK.equals(respEntity.getStatusCode())) {
// 测试发现,实际还是会成功的,若间隔一段时间之后,手工copy该URL,并在浏览器中使用,会403
// 貌似ProxyToken 不是说使用一次之后就失效,而是有个很短的时间内均有效。
// 原因:使用了Ehcache的缘故
logger.error("Second call service with same proxy ticket should faild, but success with response code "
+ status + ", content =\n" + respEntity.getBody());
} else {
logger.info("Second call service with same proxy ticket should failded with response code " + status
+ ", content =\n" + respEntity.getBody());
}
}
// 调用 staff 服务
String staffServiceUrl = staffUrl;
if (token != null) {
String proxyTicket = token.getAssertion().getPrincipal().getProxyTicketFor(staffUrl);
staffServiceUrl = staffUrl + "?ticket=" + URLEncoder.encode(proxyTicket, "UTF-8");
}
respEntity = rest.getForEntity(staffServiceUrl, String.class);
modelMap.put("staffServiceUrl", staffServiceUrl);
modelMap.put("staffServiceRespCode", respEntity.getStatusCode().value());
modelMap.put("staffServiceResp", respEntity.getBody());
return "testProxy";
}
}